{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Neural machine translation with RNN attention model\n",
    "\n",
    "In this example, we'll use PyTorch to implement GRU-based seq2seq encoder/decoder with Luong attention. We'll use this attention model for French->English neural machine translation.\n",
    "\n",
    "_This example is based on_ [https://github.com/pytorch/tutorials/blob/master/intermediate_source/seq2seq_translation_tutorial.py](https://github.com/pytorch/tutorials/blob/master/intermediate_source/seq2seq_translation_tutorial.py)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's start with the imports and the configuration. The dataset processing is implemented in the `nmt_dataset` module:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "\n",
    "import torch\n",
    "from nmt_dataset import *\n",
    "\n",
    "DATASET_SIZE = 40000\n",
    "HIDDEN_SIZE = 128"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we'll initialize the device (GPU if available, otherwise CPU):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, we'll implement the `EncoderRNN`, which combines the GRU cell with word embedding layer:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class EncoderRNN(torch.nn.Module):\n",
    "    \"\"\"The encoder\"\"\"\n",
    "\n",
    "    def __init__(self, input_size, hidden_size):\n",
    "        super(EncoderRNN, self).__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "\n",
    "        # Embedding for the input words\n",
    "        self.embedding = torch.nn.Embedding(input_size, hidden_size)\n",
    "\n",
    "        # The actual rnn sell\n",
    "        self.rnn_cell = torch.nn.GRU(hidden_size, hidden_size)\n",
    "\n",
    "    def forward(self, input, hidden):\n",
    "        \"\"\"Single sequence encoder step\"\"\"\n",
    "\n",
    "        # Pass through the embedding\n",
    "        embedded = self.embedding(input).view(1, 1, -1)\n",
    "        output = embedded\n",
    "\n",
    "        # Pass through the RNN\n",
    "        output, hidden = self.rnn_cell(output, hidden)\n",
    "        return output, hidden\n",
    "\n",
    "    def init_hidden(self):\n",
    "        return torch.zeros(1, 1, self.hidden_size, device=device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we'll implement the decoder, which includes the attention mechanism:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class AttnDecoderRNN(torch.nn.Module):\n",
    "    \"\"\"RNN decoder with attention\"\"\"\n",
    "\n",
    "    def __init__(self, hidden_size, output_size, max_length=MAX_LENGTH, dropout=0.1):\n",
    "        super(AttnDecoderRNN, self).__init__()\n",
    "        self.hidden_size = hidden_size\n",
    "        self.output_size = output_size\n",
    "        self.max_length = max_length\n",
    "\n",
    "        # Embedding for the input word\n",
    "        self.embedding = torch.nn.Embedding(self.output_size, self.hidden_size)\n",
    "\n",
    "        self.dropout = torch.nn.Dropout(dropout)\n",
    "\n",
    "        # Attention portion\n",
    "        self.attn = torch.nn.Linear(in_features=self.hidden_size,\n",
    "                                    out_features=self.hidden_size)\n",
    "\n",
    "        self.w_c = torch.nn.Linear(in_features=self.hidden_size * 2,\n",
    "                                   out_features=self.hidden_size)\n",
    "\n",
    "        # RNN\n",
    "        self.rnn_cell = torch.nn.GRU(input_size=self.hidden_size,\n",
    "                                     hidden_size=self.hidden_size)\n",
    "\n",
    "        # Output word\n",
    "        self.w_y = torch.nn.Linear(in_features=self.hidden_size,\n",
    "                                   out_features=self.output_size)\n",
    "\n",
    "    def forward(self, input, hidden, encoder_outputs):\n",
    "        embedded = self.embedding(input).view(1, 1, -1)\n",
    "        embedded = self.dropout(embedded)\n",
    "\n",
    "        # Compute the hidden state at current step t\n",
    "        rnn_out, hidden = self.rnn_cell(embedded, hidden)\n",
    "\n",
    "        # Compute the alignment scores\n",
    "        alignment_scores = torch.mm(self.attn(hidden)[0], encoder_outputs.t())\n",
    "\n",
    "        # Compute the weights\n",
    "        attn_weights = torch.nn.functional.softmax(alignment_scores, dim=1)\n",
    "\n",
    "        # Multiplicative attention context vector c_t\n",
    "        c_t = torch.mm(attn_weights, encoder_outputs)\n",
    "\n",
    "        # Concatenate h_t and the context\n",
    "        hidden_s_t = torch.cat([hidden[0], c_t], dim=1)\n",
    "\n",
    "        # Compute the hidden context\n",
    "        hidden_s_t = torch.tanh(self.w_c(hidden_s_t))\n",
    "\n",
    "        # Compute the output\n",
    "        output = torch.nn.functional.log_softmax(self.w_y(hidden_s_t), dim=1)\n",
    "\n",
    "        return output, hidden, attn_weights\n",
    "\n",
    "    def init_hidden(self):\n",
    "        return torch.zeros(1, 1, self.hidden_size, device=device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll continue with the training procedure:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(encoder, decoder, loss_function, encoder_optimizer, decoder_optimizer, data_loader, max_length=MAX_LENGTH):\n",
    "    print_loss_total = 0\n",
    "\n",
    "    # Iterate over the dataset\n",
    "    for i, (input_tensor, target_tensor) in enumerate(data_loader):\n",
    "        input_tensor = input_tensor.to(device).squeeze(0)\n",
    "        target_tensor = target_tensor.to(device).squeeze(0)\n",
    "\n",
    "        encoder_hidden = encoder.init_hidden()\n",
    "\n",
    "        encoder_optimizer.zero_grad()\n",
    "        decoder_optimizer.zero_grad()\n",
    "\n",
    "        input_length = input_tensor.size(0)\n",
    "        target_length = target_tensor.size(0)\n",
    "\n",
    "        encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device)\n",
    "\n",
    "        loss = torch.Tensor([0]).squeeze().to(device)\n",
    "\n",
    "        with torch.set_grad_enabled(True):\n",
    "            # Pass the sequence through the encoder and store the hidden states at each step\n",
    "            for ei in range(input_length):\n",
    "                encoder_output, encoder_hidden = encoder(\n",
    "                    input_tensor[ei], encoder_hidden)\n",
    "                encoder_outputs[ei] = encoder_output[0, 0]\n",
    "\n",
    "            # Initiate decoder with the GO_token\n",
    "            decoder_input = torch.tensor([[GO_token]], device=device)\n",
    "\n",
    "            # Initiate the decoder with the last encoder hidden state\n",
    "            decoder_hidden = encoder_hidden\n",
    "\n",
    "            # Teacher forcing: Feed the target as the next input\n",
    "            for di in range(target_length):\n",
    "                decoder_output, decoder_hidden, decoder_attention = decoder(\n",
    "                    decoder_input, decoder_hidden, encoder_outputs)\n",
    "                loss += loss_function(decoder_output, target_tensor[di])\n",
    "                decoder_input = target_tensor[di]  # Teacher forcing\n",
    "\n",
    "            loss.backward()\n",
    "\n",
    "            encoder_optimizer.step()\n",
    "            decoder_optimizer.step()\n",
    "\n",
    "        print_loss_total += loss.item() / target_length\n",
    "\n",
    "        it = i + 1\n",
    "        if it % 1000 == 0:\n",
    "            print_loss_avg = print_loss_total / 1000\n",
    "            print_loss_total = 0\n",
    "            print('Iteration: %d %.1f%%; Loss: %.4f' % (it, 100 * it / len(data_loader.dataset), print_loss_avg))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, let's implement the evaluation procedure:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def evaluate(encoder, decoder, input_tensor, max_length=MAX_LENGTH):\n",
    "    with torch.no_grad():\n",
    "        input_length = input_tensor.size()[0]\n",
    "        encoder_hidden = encoder.init_hidden()\n",
    "        input_tensor.to(device)\n",
    "\n",
    "        encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device)\n",
    "\n",
    "        for ei in range(input_length):\n",
    "            # Pass the sequence through the encoder and store the hidden states at each step\n",
    "            encoder_output, encoder_hidden = encoder(input_tensor[ei],\n",
    "                                                     encoder_hidden)\n",
    "            encoder_outputs[ei] += encoder_output[0, 0]\n",
    "\n",
    "        # Initiate the decoder with the last encoder hidden state\n",
    "        decoder_input = torch.tensor([[GO_token]], device=device)  # GO\n",
    "\n",
    "        # Initiate the decoder with the last encoder hidden state\n",
    "        decoder_hidden = encoder_hidden\n",
    "\n",
    "        decoded_words = []\n",
    "        decoder_attentions = torch.zeros(max_length, max_length)\n",
    "\n",
    "        # Generate the output sequence (opposite to teacher forcing)\n",
    "        for di in range(max_length):\n",
    "            decoder_output, decoder_hidden, decoder_attention = decoder(\n",
    "                decoder_input, decoder_hidden, encoder_outputs)\n",
    "            decoder_attentions[di] = decoder_attention.data\n",
    "\n",
    "            # Obtain the output word index with the highest probability\n",
    "            _, topi = decoder_output.data.topk(1)\n",
    "            if topi.item() != EOS_token:\n",
    "                decoded_words.append(dataset.output_lang.index2word[topi.item()])\n",
    "            else:\n",
    "                break\n",
    "\n",
    "            # Use the latest output word as the next input\n",
    "            decoder_input = topi.squeeze().detach()\n",
    "\n",
    "        return decoded_words, decoder_attentions[:di + 1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we'll implement a helper function, which allows us to evaluate (translate) random sequence of the training dataset:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def evaluate_randomly(encoder, decoder, n=10):\n",
    "    for i in range(n):\n",
    "        sample = random.randint(0, len(dataset.dataset) - 1)\n",
    "        pair = dataset.pairs[sample]\n",
    "        input_sequence = dataset[sample][0].to(device)\n",
    "\n",
    "        output_words, attentions = evaluate(encoder, decoder, input_sequence)\n",
    "\n",
    "        print('INPUT: %s; TARGET: %s; RESULT: %s' % (pair[0], pair[1], ' '.join(output_words)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll continue with two functions that allows us to see the attention scores over the input sequence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.ticker as ticker\n",
    "\n",
    "def plot_attention(input_sentence, output_words, attentions):\n",
    "    # Set up figure with colorbar\n",
    "    fig = plt.figure()\n",
    "    ax = fig.add_subplot(111)\n",
    "    cax = ax.matshow(attentions.numpy(), cmap='bone')\n",
    "    fig.colorbar(cax)\n",
    "\n",
    "    # Set up axes\n",
    "    ax.set_xticklabels([''] + input_sentence.split(' ') +\n",
    "                       ['<EOS>'], rotation=90)\n",
    "    ax.set_yticklabels([''] + output_words)\n",
    "\n",
    "    # Show label at every tick\n",
    "    ax.xaxis.set_major_locator(ticker.MultipleLocator(1))\n",
    "    ax.yaxis.set_major_locator(ticker.MultipleLocator(1))\n",
    "\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "def evaluate_and_plot_attention(input_sentence, encoder, decoder):\n",
    "    input_tensor = dataset.sentence_to_sequence(input_sentence).to(device)\n",
    "\n",
    "    output_words, attentions = evaluate(encoder=encoder,\n",
    "                                        decoder=decoder,\n",
    "                                        input_tensor=input_tensor)\n",
    "\n",
    "    print('INPUT: %s; OUTPUT: %s' % (input_sentence, ' '.join(output_words)))\n",
    "    plot_attention(input_sentence, output_words, attentions)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we'll initialize the training dataset:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset = NMTDataset('data/eng-fra.txt', DATASET_SIZE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll continue with initializing the encoder/decoder model and the training framework components:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "enc = EncoderRNN(dataset.input_lang.n_words, HIDDEN_SIZE).to(device)\n",
    "dec = AttnDecoderRNN(HIDDEN_SIZE, dataset.output_lang.n_words, dropout=0.1).to(device)\n",
    "\n",
    "train_loader = torch.utils.data.DataLoader(dataset,\n",
    "                                           batch_size=1,\n",
    "                                           shuffle=False)\n",
    "\n",
    "encoder_optimizer = torch.optim.Adam(enc.parameters())\n",
    "decoder_optimizer = torch.optim.Adam(dec.parameters())\n",
    "loss_function = torch.nn.NLLLoss()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, we'll can run the training:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 1000 2.5%; Loss: 3.2344\n",
      "Iteration: 2000 5.0%; Loss: 2.6458\n",
      "Iteration: 3000 7.5%; Loss: 2.2991\n",
      "Iteration: 4000 10.0%; Loss: 2.1474\n",
      "Iteration: 5000 12.5%; Loss: 2.0301\n",
      "Iteration: 6000 15.0%; Loss: 1.9312\n",
      "Iteration: 7000 17.5%; Loss: 1.8323\n",
      "Iteration: 8000 20.0%; Loss: 1.7041\n",
      "Iteration: 9000 22.5%; Loss: 1.6163\n",
      "Iteration: 10000 25.0%; Loss: 1.6229\n",
      "Iteration: 11000 27.5%; Loss: 1.5275\n",
      "Iteration: 12000 30.0%; Loss: 1.4935\n",
      "Iteration: 13000 32.5%; Loss: 1.4158\n",
      "Iteration: 14000 35.0%; Loss: 1.3289\n",
      "Iteration: 15000 37.5%; Loss: 1.3238\n",
      "Iteration: 16000 40.0%; Loss: 1.3008\n",
      "Iteration: 17000 42.5%; Loss: 1.3011\n",
      "Iteration: 18000 45.0%; Loss: 1.2671\n",
      "Iteration: 19000 47.5%; Loss: 1.2171\n",
      "Iteration: 20000 50.0%; Loss: 1.1584\n",
      "Iteration: 21000 52.5%; Loss: 1.1282\n",
      "Iteration: 22000 55.0%; Loss: 1.0746\n",
      "Iteration: 23000 57.5%; Loss: 1.0888\n",
      "Iteration: 24000 60.0%; Loss: 1.0930\n",
      "Iteration: 25000 62.5%; Loss: 1.1087\n",
      "Iteration: 26000 65.0%; Loss: 1.0284\n",
      "Iteration: 27000 67.5%; Loss: 1.0434\n",
      "Iteration: 28000 70.0%; Loss: 1.0601\n",
      "Iteration: 29000 72.5%; Loss: 0.9805\n",
      "Iteration: 30000 75.0%; Loss: 0.9516\n",
      "Iteration: 31000 77.5%; Loss: 0.9791\n",
      "Iteration: 32000 80.0%; Loss: 0.9477\n",
      "Iteration: 33000 82.5%; Loss: 0.9331\n",
      "Iteration: 34000 85.0%; Loss: 0.8922\n",
      "Iteration: 35000 87.5%; Loss: 0.9079\n",
      "Iteration: 36000 90.0%; Loss: 0.8848\n",
      "Iteration: 37000 92.5%; Loss: 0.8791\n",
      "Iteration: 38000 95.0%; Loss: 0.8695\n",
      "Iteration: 39000 97.5%; Loss: 0.8856\n",
      "Iteration: 40000 100.0%; Loss: 0.8629\n"
     ]
    }
   ],
   "source": [
    "train(enc, dec, loss_function, encoder_optimizer, decoder_optimizer, train_loader)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's see how the model translates some randomly selected sentences:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INPUT: vous etes merveilleuse .; TARGET: you re wonderful .; RESULT: you re wonderful .\n",
      "INPUT: c est un bon mari pour moi .; TARGET: he is a good husband to me .; RESULT: he is a good husband to me .\n",
      "INPUT: c est un tres gentil garcon .; TARGET: he s a very nice boy .; RESULT: he s a very nice boy .\n",
      "INPUT: je suis tout a fait pour .; TARGET: i m all for that .; RESULT: i m all used to it .\n",
      "INPUT: je suis deshydratee .; TARGET: i m dehydrated .; RESULT: i m dehydrated .\n",
      "INPUT: je ne suis pas particulierement impressionnee .; TARGET: i m not particularly impressed .; RESULT: i m not impressed .\n",
      "INPUT: il est tres flexible .; TARGET: he s very flexible .; RESULT: he s very flexible .\n",
      "INPUT: desole .; TARGET: i m sorry .; RESULT: i m sorry .\n",
      "INPUT: c est un de mes voisins .; TARGET: he is one of my neighbors .; RESULT: he s a afraid of my neighbors .\n",
      "INPUT: il a huit ans .; TARGET: he s eight years old .; RESULT: he is eight years old .\n"
     ]
    }
   ],
   "source": [
    "evaluate_randomly(enc, dec)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, let's visualize the decoder attention over the elements of the input sequence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7fb03c9f0438>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAY8AAAECCAYAAAAGtFvhAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAALPklEQVR4nO3dX4jl9XnH8c/T3Y1mTWjaxpbqSvUipEggWgZJaynUtNU0IblVSC5KYW+a1pRASHrX+xLSi1BYjG0hNlKMgSA2G0sMIdCarLq1/ksQa+K/oqZNY3rhvzy92BGMbp3ztHPm/MZ9vWBx5ng4fPiu63t/55yZqe4OAEz8zKYHALD/iAcAY+IBwJh4ADAmHgCMiQcAY4uNR1VdVVXfqaqHquqTm96zRFV1QVXdXlX3V9V9VXXtpjctWVUdqKq7q+qWTW9Zsqp6W1XdVFUPVtUDVfXrm960RFX1p9t/7u6tqi9U1dmb3rSXFhmPqjqQ5LNJ3pfk4iTXVNXFm121SC8m+Xh3X5zkPUn+yDm9rmuTPLDpEfvAXyb5Snf/apJ3x5m9RlWdn+RPkmx197uSHEhy9WZX7a1FxiPJZUke6u6Hu/v5JDcm+dCGNy1Odz/Z3Xdtf/xsTv0hP3+zq5apqo4keX+S6za9Zcmq6meT/FaSzyVJdz/f3T/c7KrFOpjkzVV1MMnhJE9seM+eWmo8zk/y6Cs+fyz+p/i6qurCJJcmuWOzSxbrM0k+keQnmx6ycBcleTrJX28/xXddVZ2z6VFL092PJ/mLJN9P8mSS/+rur2521d5aajwYqKq3JPliko919482vWdpquoDSZ7q7js3vWUfOJjk15L8VXdfmuS/k3jN8VWq6udy6tmQi5Kcl+ScqvrwZlftraXG4/EkF7zi8yPbt/EqVXUop8JxQ3ffvOk9C3V5kg9W1SM59RToFVX1+c1OWqzHkjzW3S9fwd6UUzHhp/1Okn/r7qe7+4UkNyf5jQ1v2lNLjce3k7yjqi6qqjfl1AtRX97wpsWpqsqp56Yf6O5Pb3rPUnX3p7r7SHdfmFP/LX2tu8+ovyWuqrv/PcmjVfXO7Zvem+T+DU5aqu8neU9VHd7+c/jenGFvLDi46QGn090vVtVHkxzPqXcxXN/d92141hJdnuQjSf61qk5u3/Zn3X3rBjex//1xkhu2/+L2cJI/2PCexenuO6rqpiR35dS7Hu9Ocmyzq/ZW+ZbsAEwt9WkrABZMPAAYEw8AxsQDgDHxAGBs0fGoqqOb3rBfOKvVOKfVOKfVnalnteh4JDkjf1P+j5zVapzTapzT6s7Is1p6PABYoLV8keDbf/5AX3jBof/34zz9g5dy7i8c2IVFyXfvObwrj7NUL+S5HMpZm56xeM5pNc5pdW/0s3o2//lMd5/76tvX8u1JLrzgUL51/IKd77iHrjzvkk1PANh3/rFv+t7pbve0FQBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBjK8Wjqq6qqu9U1UNV9cl1jwJg2XaMR1UdSPLZJO9LcnGSa6rq4nUPA2C5VrnyuCzJQ939cHc/n+TGJB9a7ywAlmyVeJyf5NFXfP7Y9m0AnKF27QXzqjpaVSeq6sTTP3hptx4WgAVaJR6PJ3nlz5Q9sn3bT+nuY9291d1bu/VzxwFYplXi8e0k76iqi6rqTUmuTvLl9c4CYMkO7nSH7n6xqj6a5HiSA0mu7+771r4MgMXaMR5J0t23Jrl1zVsA2Cd8hTkAY+IBwJh4ADAmHgCMiQcAY+IBwJh4ADAmHgCMiQcAY+IBwJh4ADAmHgCMrfSNEae+e8/hXHneJet46DeU40+c3PSE0/J7B+zElQcAY+IBwJh4ADAmHgCMiQcAY+IBwJh4ADAmHgCMiQcAY+IBwJh4ADAmHgCMiQcAY+IBwJh4ADC2Yzyq6vqqeqqq7t2LQQAs3ypXHn+T5Ko17wBgH9kxHt39jST/sQdbANgnvOYBwNiu/Qzzqjqa5GiSnJ3Du/WwACzQrl15dPex7t7q7q1DOWu3HhaABfK0FQBjq7xV9wtJ/inJO6vqsar6w/XPAmDJdnzNo7uv2YshAOwfnrYCYEw8ABgTDwDGxAOAMfEAYEw8ABgTDwDGxAOAMfEAYEw8ABgTDwDGxAOAMfEAYEw8ABgTDwDGxAOAMfEAYEw8ABgTDwDGxAOAMfEAYEw8ABgTDwDGxAOAMfEAYEw8ABgTDwDGxAOAsR3jUVUXVNXtVXV/Vd1XVdfuxTAAluvgCvd5McnHu/uuqnprkjur6rbuvn/N2wBYqB2vPLr7ye6+a/vjZ5M8kOT8dQ8DYLlGr3lU1YVJLk1yxzrGALA/rPK0VZKkqt6S5ItJPtbdPzrNvz+a5GiSnJ3DuzYQgOVZ6cqjqg7lVDhu6O6bT3ef7j7W3VvdvXUoZ+3mRgAWZpV3W1WSzyV5oLs/vf5JACzdKlcelyf5SJIrqurk9q/fX/MuABZsx9c8uvubSWoPtgCwT/gKcwDGxAOAMfEAYEw8ABgTDwDGxAOAMfEAYEw8ABgTDwDGxAOAMfEAYEw8ABgTDwDGVv5Jguy+K8+7ZNMT9o3jT5zc9ITX8PvHmcyVBwBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj4gHA2I7xqKqzq+pbVfUvVXVfVf35XgwDYLlW+XkezyW5ort/XFWHknyzqv6hu/95zdsAWKgd49HdneTH258e2v7V6xwFwLKt9JpHVR2oqpNJnkpyW3ffsd5ZACzZSvHo7pe6+5IkR5JcVlXvevV9qupoVZ2oqhMv5Lnd3gnAgozebdXdP0xye5KrTvPvjnX3VndvHcpZu7UPgAVa5d1W51bV27Y/fnOS303y4LqHAbBcq7zb6peT/G1VHcip2Px9d9+y3lkALNkq77a6J8mle7AFgH3CV5gDMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMLbKt2SHjbvyvEs2PeE1jj9xctMTXmOJ58QbkysPAMbEA4Ax8QBgTDwAGBMPAMbEA4Ax8QBgTDwAGBMPAMbEA4Ax8QBgTDwAGBMPAMbEA4Ax8QBgbOV4VNWBqrq7qm5Z5yAAlm9y5XFtkgfWNQSA/WOleFTVkSTvT3LdeucAsB+seuXxmSSfSPKT/+0OVXW0qk5U1YkX8tyujANgmXaMR1V9IMlT3X3n692vu49191Z3bx3KWbs2EIDlWeXK4/IkH6yqR5LcmOSKqvr8WlcBsGg7xqO7P9XdR7r7wiRXJ/lad3947csAWCxf5wHA2MHJnbv760m+vpYlAOwbrjwAGBMPAMbEA4Ax8QBgTDwAGBMPAMbEA4Ax8QBgTDwAGBMPAMbEA4Ax8QBgTDwAGBt9V13YlONPnNz0hNe48rxLNj0BNsaVBwBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj4gHA2Erfkr2qHknybJKXkrzY3VvrHAXAsk1+nsdvd/cza1sCwL7haSsAxlaNRyf5alXdWVVH1zkIgOVb9Wmr3+zux6vqF5PcVlUPdvc3XnmH7agcTZKzc3iXZwKwJCtdeXT349v/fCrJl5Jcdpr7HOvure7eOpSzdnclAIuyYzyq6pyqeuvLHyf5vST3rnsYAMu1ytNWv5TkS1X18v3/rru/stZVACzajvHo7oeTvHsPtgCwT3irLgBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj4gHAmHgAMCYeAIyJBwBj1d27/6BVTyf53i481NuTPLMLj3MmcFarcU6rcU6re6Of1a9097mvvnEt8dgtVXWiu7c2vWM/cFarcU6rcU6rO1PPytNWAIyJBwBjS4/HsU0P2Eec1Wqc02qc0+rOyLNa9GseACzT0q88AFgg8QBgTDwAGBMPAMbEA4Cx/wH3p0EG0Y/RNgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 480x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "output_words, attentions = evaluate(\n",
    "    enc, dec, dataset.sentence_to_sequence(\"je suis trop froid .\").to(device))\n",
    "plt.matshow(attentions.numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's see the translation and attention scores with a few more samples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INPUT: elle a cinq ans de moins que moi .; OUTPUT: she is five years younger than me .\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INPUT: elle est trop petit .; OUTPUT: she is too short .\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAW0AAAD9CAYAAAB3ECbVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAXaklEQVR4nO3df5xddX3n8dfbACIIogxWIEGwDbUpooQItmKlFWygrbAP2/KjW2tLzW4tPtxlcYtbH+iiXWRZ7WqL1lFAwK00dcXN2rhx64/iatVMBIGkwiOLCgGVjaKkRgXmvvePc2ZymEzm3pk595577ryfPM5j7jn33O/3e4F88p3P+f6QbSIioh2e1HQDIiKidwnaEREtkqAdEdEiCdoRES2SoB0R0SIJ2hERLZKgHRHRIgnaEREtkqAdEdEiCdox8lT4mKSfa7otEYuVoB1LwcuBFwJ/2HRDIhYrQTuWgosoAvZvSNqv6cZELEaCdow0SWPAz9v+BPD3wLkNNyliURK0Y9T9LvDh8vX1JEUSLZegHaPuDyiCNbY3A0dKWtFskyIWLkE7Rpakw4C/tP1A5fKlwFhDTYpYNGUThIiI9khPO0aSpNdIWlm+lqTrJT0i6Q5JJzXdvoiFStCOUfV64Bvl6wuAE4HjgEuAdzfUplhCJF0n6SFJd+3jfUl6t6TtZWdidS/lJmjHqHrc9mPl618HbrT9Xdt/DxzcYLti6fggsHaO988CVpbHOuC9vRSaoB2jqiPpSEkHAi+jGKM95SkNtSmWENu3At+b45ZzKDoTtv1F4DBJR3YrN7PDYlRdDkwAy4ANtrcCSHopcG+TDYvhtXbtWu/cubOne7ds2bIV+HHl0rjt8XlUdzRwf+V8R3ntW3N9KEE7AJB0k+3f7XatLWx/XNKzgUNsP1x5awI4r6FmxZDbuXMnExMTPd0r6ce21/S5SXtJ0I4pP189kbQMOLmhttTlGcAfS5r6bluB99j+ToNtiiE3wGHQDwDViV7Ly2tzSk57iZP0Rkm7gBPLIXGPlOcPAf+j4eYtmKQXA5vL0xvLA+BL5XsRezEw2en0dNRgA/CqchTJi4Af2J4zNQLpaQ+18iHaa4HTKP5/+j/Ae23/eM4PzoPtK4ErJV1p+411lTsE3gGca/u2yrUNkm4B3gec2kyzYrgZU09PW9KHgdOBMUk7gDcD+wPY/itgI3A2sB3YDfx+L+UmaA+3G4FdwF+U5xcCNwG/VVcFkp5r+2vA3842TtT2V+qqa8AOnRGwAbB9u6RDmmhQtIChU1N2xPYFXd438MfzLXekgrak04CVtq+XdATwVNtfb7pdi3CC7VWV889I2lZzHZdQjBF9xyzvGfiVmusbFEl6+oyHkEh6BkkLxhyGfWmPkQnakt4MrAF+lmJVt/2BDwFtzl9+RdKLyjGcSDqVYvRDbWyvK1+eNTPtUqZn2urPgU9KuhSY+m3hZOCq8r2IvRjoJGgPzL8ATqL8A2r7wX79GizpybZ/0u1aDU4GviDpvvL8GOBuSXdS/HZ1Yo11fQGYmR6Z7Vor2B6X9CDwVoqRMQa2AW+z/T8bbVwMtfS0B+dR25ZkAEn9nKr8j+wdzGa7tlhzTYGthaRnUQzof0q5kJLKtw4FDup3/f1k++PAx5tuR7SH7bpGhvTNKAXt9ZLeRzEV9DUUi9+/v84KBh3gbH9T0vOBl5SXPmf7qzVX86vAqynGiL6zcv0R4D/UXNfASFpv+7fL11fZ/pPKe5+0/fLmWhfDLD3tAbH9XySdSRFsfha43Pb/rrmaaoB7B3uC9i76EOAkvR54DfDR8tKHJI3b/os5PjYvtm8AbpD0Stv/va5yh8DKyuszgT+pnB8x4LZEi9Q15K9fRiZoA5RBuu5AXS1/0AHuIuBU2z+EosdIkYapLWhXfF7StcBRts+StAr4BdvX9qGuQZjrT95w/6mMxhQPIptuxdxaP/RJ0q7KTL7qsUvSI32qdrmkQ8uZTB+Q9BVJ/fh1W8Bk5XySPb37ul0PbAKOKs/vAf5Nn+oahIMknSTpZMp0lqTVU+dNNy6Gl+2ejqa0vqdtu4mJEn9g+12SfhU4nGLH75uAT9Zcz/UU065vKc/PBfrV8x2zvV7SGwFsPy5pstuHhti32JOj/zZPzNd/e/DNiVbIg8j+KydL7JPtudazXXC15c9fo1gPd6uk2nvAtt8p6bMU09gBfn+2WX41+aGkwylTB1NrIfSprr6z/ctNtyHax+RB5CBsofh3LfbkKqcCqIHn9KNOSZvKsi8rx4PX+tdzucreVtvPZc/kkH66hGIBm+dI+jzFw7rfHEC9fSPpKcDx1RE3ko4BJmfs0B4xLZNr+sz2cQCSngT8DnCc7SvKP5xdd4FYoIuANwHbbO8u66o1/2t7UtLdko6xfV/3TyzaNuAWioVrdgEfo8hrt9njwEclnTj1MBf4AMVInwTtmNWw97Rb/yCy4hrgRRSbuEIReP6yj3X9FHsmv+ziiTnTujwd2CrpU5I2TB19qAeKxameC/wnitEpx1Pk6Vur3CPyFmBqvPYxwBG2a10KIEaJe/6nKa3vaVecanu1pNsAbD8s6YCW13Ugxaa0U0SxdkY/DGJxqiZ8ABineKj7qvJnxKxc4yp//TJKQfuxMg889SDtCGrOMzdQ1362/6F6oczT9kPfF6dqgu2vlUMzjwfOZ8/s0ohZdTJ6ZGDeTfGr8DMl/RnFQ7Q3tbEuSX9EsfnBcyTdUXnrEODzddUzwyAXp9qLpGfZ7tdQvGspetx3zlyqNaIqq/wNkO3/JmkL8DKKNMK5tv+ppXX9NfAJ4Ergssr1XX0awggDWJyqi2sphlD2w3rgXcAVfSo/RsiwP4gcmaANxa/CwNfaXpftH1CMkZ5z54ua6/zmoOraR/39CtjY3g08rV/lxwix09OOiGiT9LQjIlrCwOSQB+1RGqc9TdK67nelrmGoaxS/06jWNYrfaTbDvmDUSAZtio1qU1c76hrF7zSqdY3id9rLsAftpEciIkrOg8jFm9rzcRCfO/nkk+ddzzHHHMOaNWvmXdeWLVvmXRcs/N/HMNc1it9pVOtqwXfaaXtROxPlQWSLTEwMbgJgH1ZyjQhY9NDVBO2IiJYoRo9kGntERGtkwaiIiLZoeGRILxK0IyJK2W4sIqJlMuQvIqJF0tOOiGgJ20wO+SYIfZnGLukbksb6UXZERD9lj8iIiBYZ9iF/i+5pSzpY0t9J+qqkuySdV771OklfkXSnpOdW7r1O0pcl3SbpnMXWHxFRl6nRI3UtGCVpraS7JW2XdNks7x8j6TNlPLxD0tndyqwjPbIWeND2822fAPyv8vpO26uB9wKXltf+FPi07VOAXwaulnRwDW2IiKhFXUG73Pz7GuAsYBVwgaRVM257E7De9kkUG0+/p1u5dQTtO4EzJV0l6SXlVlkAHy1/bgGOLV+/HLhM0u3AZ4EDKTaQfQJJ6yRNSGr9buAR0SLlg8hejh6cAmy3fa/tR4GbgZnZBQOHlq+fBjzYrdBF57Rt3yNpNXA28DZJnyrf+kn5c7JSj4BX2r67S5njwDgMdlWxiFjaap5cczRwf+V8B3DqjHveAnxS0uuAg4EzuhVaR077KGC37Q8BVwOr57h9E0WuW+VnT1ps/RERdeqUa2p3O4CxqYxAeSxk44YLgA/aXk7R8b1J0pxxuY7RI8+jyE13gMeAPwI+so973wr8V+COsmFfB369hjZERNRiHsP5dtpeM8f7DwArKufLy2tVF1E8F8T2P0o6EBgDHtpXoXWkRzZR9KCrjq28PwGcXr7+EfCvFltnRES/1DghcjOwUtJxFMH6fODCGffcB7wM+KCkn6N4zvf/5io047QjIkqmvrVHbD8u6WKKTu0y4DrbWyVdAUzY3gD8O+D9kv5tWf2r3SWpnqAdETGl5mnstjcCG2dcu7zyehvw4vmUmaAdEVHK0qwRES2ToB0R0SJZTzsiojWaXcGvFwnaERElu9Yhf32RoB0RUTHsmyAkaEdElOocp90vCdoRERUZPRIR0Rbz2OCgKQnaERFVCdoREe3RmUzQjohohWLIX4J2RERrJGhHRLRGHkRGRLSKOwnaERGt0Iac9qI39u2VpC8Mqq6IiIVyp9PT0ZSB9bRt/+Kg6oqIWKgh72gPtKf9z+XPIyXdKul2SXdJesmg2hARMScbd3o7mtJETvtCYJPtP5O0DDiogTZERMxq2HPaTQTtzcB1kvYHPmb79pk3SFoHrBt4yyJiSWvDHpEDS49MsX0r8EvAA8AHJb1qlnvGba+xvWbQ7YuIpc3lolHdjqYMvKct6dnADtvvl/RkYDVw46DbERGxFxtPZhOEmU4H3iDpMeCfgb162hERTRn29Mggh/w9tfx5A3DDoOqNiJiPIY/ZmREZETGlDQ8iE7QjIqa0YBp7gnZExDTTyYPIiIj2SE87IqIl2rDKX4J2RERVgnZERHt4uFPaCdoREVVJj7SIpIHVNaj/MQb5nSJaz6bT4AYHvUjQjogotWFyzcBX+YuIGFqm1k0QJK2VdLek7ZIu28c9vy1pm6Stkv66W5npaUdEVNXU0y43ebkGOBPYAWyWtMH2tso9K4E3Ai+2/bCkZ3YrNz3tiIhpva2l3WMK5RRgu+17bT8K3AycM+Oe1wDX2H4YwPZD3QpN0I6IqOh03NMBjEmaqBwzd9s6Gri/cr6jvFZ1PHC8pM9L+qKktd3al/RIRETJZU67Rztr2F1rP2AlxT4Dy4FbJT3P9vf39YH0tCMiKmpMjzwArKicLy+vVe0ANth+zPbXgXsogvg+JWhHRFTUGLQ3AyslHSfpAOB8YMOMez5G0ctG0hhFuuTeuQpNeiQiYlp9m/baflzSxcAmYBlwne2tkq4AJmxvKN97uaRtwCTwBtvfnavcWoK2pMOAC22/p47yIiIaUfMqf7Y3AhtnXLu88trAJeXRk7rSI4cBr62prIiIRhjwpHs6mlJX0H478NOSbpd0dXncJelOSecBqLDX9YiIYVJjTrsv6sppXwacYPsFkl4J/Gvg+cAYxSygW4FfBF4w87rtb9XUhoiIxWk4IPeiH6NHTgM+bHvS9neAfwBeOMf1vUhaNzVgvQ/ti4jYpzrXHumHoRw9YnscGAeQNNx/7UXESFkqPe1dwCHl688B50laJukI4JeAL89xPSJiKEwtzTryOW3b3y3nzt8FfAK4A/gqxb+Df2/725JuAX5h5vU66o+IqIWNl8omCLYvnHHpDTPed3ntDUREDKnsERkR0SLDntNO0I6ImFLzjMh+SNCOiCi1YY/IBO2IiGmmMzncSe0E7YiIKUmPRES0TIJ2RER7DHnMTtBuiqSB1HPYYT81kHoA7vy/2wZW14rDDx9YXbF05EFkRESbzG9j30YkaEdETDOdpTKNPSJiFCQ9EhHRJgnaERHt4OS0IyLaZcg72gnaERF7DP8ekQnaERFTTEaPRES0hUlOOyKiVYY9PbKgjX0lfUPS2EIrlfQCSWcv9PMREf3hcghJD0dD6tqNvWeS9gNeACRoR8Rw8Qjsxi7pYGA9sBxYBry1fOt1kn4D2B/4Ldtfk/QM4DrgOcBuYJ3tOyS9Bfjp8vp9wIuBp0g6DbjS9t/U+7UiIhamMznc6ZFectprgQdt/xqApKcBVwE7ba+W9FrgUuAPgf8I3Gb7XEm/AtxI0asGWAWcZvtHkl4NrLF98WwVSloHrFvE94qImLc2rPLXS3rkTuBMSVdJeontH5TXP1r+3AIcW74+DbgJwPangcMlHVq+t8H2j3pplO1x22tsr+nl/oiIWoxCesT2PZJWU+Sg3ybpU+VbPyl/TvZSDvDDhTUxImJQhn9yTdeetqSjgN22PwRcDaye4/bPAb9Tfu50ihTKI7Pctws4ZN6tjYjos2HvafeSHnke8GVJtwNvBt42x71vAU6WdAfwduD39nHfZ4BVkm6XdN482hsR0VfuuKejKb2kRzYBm2ZcPrby/gRwevn6e8C5s5Txlhnn3wNeON/GRkT0U92r/ElaC7yLYuTdB2y/fR/3vRL4CPDCMqbu08DHaUdEDLO60iOSlgHXAGdRjJ67QNKqWe47BHg98KVe2pegHRExrbeA3WNO+xRgu+17bT8K3AycM8t9b6UYRv3jXgpN0I6ImOJac9pHA/dXzneU16aVI/NW2P67XpuYBaMiIirmMTJkTFI1/zxue7zXD0t6EvBO4NW9ty5BOyJi2jxnRO7sMgHwAWBF5Xx5eW3KIcAJwGclATwL2CDpFXM9jEzQjoiYZlzfJgibgZWSjqMI1ucDF07XVMwun14tVdJngUszeiQiolcGd3o7uhZlPw5cTDFk+p+A9ba3SrpC0isW2sT0tEfc97//nYHVteLwwwdW1yBnpJW/usYSUef/W7Y3AhtnXLt8H/ee3kuZCdoRERXDvvZIgnZERKkNS7MmaEdETLHpTGY39oiI9khPOyKiPUyCdkREK9jJaUdEtIhxL4OwG5SgHRFRkZ52RESLdOqbxt4XCdoREaVirewE7YiI9kh6JCKiPTLkLyKiRfIgcgEkrQPWNd2OiFhqTKcz2XQj5jSUQbvcsmccQNJw/7UXESMjk2siIlpm2IN2ozvXSNoo6agm2xARUVUM++t+NKXRnrbts5usPyLiiZwhfxERbWIyuSYiohXsTGOPiGiRZvPVvUjQjoioyNojEREtkp52RESLJGhHRLSFM+QvIqI1DHSctUcW5fhVq3jP+vUDqeuME04YSD2xeJIGVtdBBx06sLpicXbvfmSRJWT0SEREqyRoR0S0SIJ2RERLFM8hM047IqIljDONPSKiPbJHZEREiySnHRHRGk5OOyKiLdqwR2Sj241FRAybOrcbk7RW0t2Stku6bJb3L5G0TdIdkj4l6dndykzQjoio6HQ6PR3dSFoGXAOcBawCLpC0asZttwFrbJ8IfAT4z93KTdCOiJhmcKe3o7tTgO2277X9KHAzcM4TarM/Y3t3efpFYHm3QhO0IyIq3OM/wJikicqxbkZRRwP3V853lNf25SLgE93alweRERGleT6I3Gl7TR31SvqXwBrgpd3uHcqgXf6NtQ7gmUce2XBrImIpqXH0yAPAisr58vLaE0g6A/hT4KW2f9Kt0KFMj9get73G9prDnv70ppsTEUtGMU67l6MHm4GVko6TdABwPrCheoOkk4D3Aa+w/VAvhQ5lTzsioim9jAzphe3HJV0MbAKWAdfZ3irpCmDC9gbgauCpwN+Wa8TfZ/sVc5WboB0RUap7co3tjcDGGdcur7w+Y75lJmhHREzLHpEREa1isvZIRERrDPvaIwnaERHTXNuDyH5J0I6IKGW7sYiIlkl6JCKiRRK0IyJaI0P+IiJaJRv7LtI927btPOOEE745z4+NATv70Z7U1dp6FlzX7t2PDKyuBcp/qz267vwyFxs6ncnFFNF3Qx+0bR8x389ImqhrycTUNRr1pK721DPoup6o963EmjL0QTsiYpAStCMiWiRBuxnjqas1dY3idxrVukbxO+1l2CfXaNj/VomIGJQD9n+yx8a67q0LwLe+fe+WJvLuo9rTjoiYNwOdIe9pJ2hHRFQMe3okQTsiYlqG/EVEtEqCdkRES9S9R2Q/JGhHREwzzjT2iIj2yIJREREtkvRIRESLJGhHRLSE7YzTjohok/S0IyJapNNJTzsioj3S046IaAtj0tOOiGiFzIiMiGiZBO2IiBZJ0I6IaA3TydojERHt0Iac9pOabkBExFApInf3oweS1kq6W9J2SZfN8v6TJf1N+f6XJB3brcwE7YiIae75n24kLQOuAc4CVgEXSFo147aLgIdt/wzw58BV3cpN0I6IqLA7PR09OAXYbvte248CNwPnzLjnHOCG8vVHgJdJ0lyFJqcdEVFR4zT2o4H7K+c7gFP3dY/txyX9ADgc2LmvQhO0IyL22ASM9XjvgZImKufjtsf70KYnSNCOiCjZXltjcQ8AKyrny8trs92zQ9J+wNOA785VaHLaERH9sRlYKek4SQcA5wMbZtyzAfi98vVvAp92lzGH6WlHRPRBmaO+mCLlsgy4zvZWSVcAE7Y3ANcCN0naDnyPIrDPScM+kDwiIvZIeiQiokUStCMiWiRBOyKiRRK0IyJaJEE7IqJFErQjIlokQTsiokUStCMiWuT/Ay6T90SSSkePAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INPUT: je ne crains pas de mourir .; OUTPUT: i m not to die .\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INPUT: c est un jeune directeur plein de talent .; OUTPUT: he s a young person .\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "evaluate_and_plot_attention(\"elle a cinq ans de moins que moi .\", enc, dec)\n",
    "\n",
    "evaluate_and_plot_attention(\"elle est trop petit .\", enc, dec)\n",
    "\n",
    "evaluate_and_plot_attention(\"je ne crains pas de mourir .\", enc, dec)\n",
    "\n",
    "evaluate_and_plot_attention(\"c est un jeune directeur plein de talent .\", enc, dec)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
